package com.zimin.redis.aop.aspect;

import com.zimin.common.exception.GraceException;
import com.zimin.common.utils.AopUtils;
import com.zimin.common.utils.ServerRequestContextHolder;
import com.zimin.redis.utils.RedisOperator;
import com.zimin.shared.annotation.RedisLock;
import com.zimin.shared.enums.ResponseStatusEnum;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * redis锁切面,方法上添加这个注解后，只允许在5秒内请求一次
 *
 * @author zimin
 * @since 2021/11/15 5:17 下午
 */
@Slf4j
@Aspect
@Component
public class RedisLockAspect {

    /**
     * 请求的key
     */
    private static final String KEY = "mine:request:lock:%s:%s";

    /**
     * key的过期时间
     */
    private static final Short TIME = 5;

    private static final Integer VALUE = 1;

    @Autowired
    private RedisOperator redisOperator;

    @Pointcut("@annotation(com.zimin.shared.annotation.RedisLock)")
    public void redisLock() {
    }

    @Around("@annotation(redisLock)")
    public Object redisLock(ProceedingJoinPoint joinPoint, RedisLock redisLock) throws Throwable {
        var method = AopUtils.getMethod(joinPoint);
        var request = ServerRequestContextHolder.get();
        var ipAddress = request.getRemoteAddress().getAddress().getHostAddress();
        var name = method.getName();
        var key = String.format(KEY, ipAddress, name);
        var value = redisOperator.get(key);
        GraceException.isNotNull(value, ResponseStatusEnum.REDIS_LOCK);
        redisOperator.set(key, VALUE, TIME);
        return joinPoint.proceed();
    }

}
